package org.example.campusforum.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * JWT拦截器
 *
 * 实现HandlerInterceptor接口，用于拦截HTTP请求并验证JWT令牌。
 * 在请求处理前验证用户身份，在请求完成后清理线程本地变量。
 *
 * @author CampusForum Team
 * @version 1.0
 * @since 2024
 */
@Component
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {

    /**
     * 请求预处理方法
     *
     * 在控制器方法执行前调用，用于验证JWT令牌并提取用户信息。
     * 如果令牌有效，将用户ID存储到ThreadLocal中供后续使用。
     *
     * @param request HTTP请求对象
     * @param response HTTP响应对象
     * @param handler 处理器对象
     * @return true表示继续处理请求，false表示拦截请求
     * @throws Exception 处理过程中可能抛出的异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        // 从Authorization请求头获取Token
        String token = request.getHeader("Authorization");
        if (token == null || token.trim().isEmpty()) {
            response.sendError(401, "缺少Authorization头");
            return false;
        }

        // 处理Bearer前缀（如果存在）
        if (token.startsWith("Bearer ")) {
            token = token.replaceFirst("^Bearer\\s+", "");
        }

        try {
            // 验证Token并获取用户信息
            Claims claims = JwtUtils.parseToken(token);
            Long userId = Long.valueOf(claims.get("userId").toString());
            // 将用户ID存储到ThreadLocal中
            BaseContext.setCurrentId(userId);
            return true;
        } catch (JwtException e) {
            log.error("Token验证失败: {}", e.getMessage());
            response.sendError(401, "Token无效或已过期");
            return false;
        }
    }

    /**
     * 请求完成后处理方法
     *
     * 在整个请求处理完成后调用，用于清理ThreadLocal变量，
     * 避免内存泄漏问题。
     *
     * @param request HTTP请求对象
     * @param response HTTP响应对象
     * @param handler 处理器对象
     * @param ex 处理过程中抛出的异常（如果有）
     * @throws Exception 处理过程中可能抛出的异常
     */
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
        // 请求完成后清理ThreadLocal，避免内存泄漏
        BaseContext.removeCurrentId();
        log.debug("ThreadLocal已清理");
    }
}
